<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频截图工具 - 基于FFmpeg.wasm</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/ffmpeg/0.11.6/ffmpeg.min.js"></script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --warning-color: #feca57;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --glass-bg: rgba(255, 255, 255, 0.25);
        --glass-border: rgba(255, 255, 255, 0.18);
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        transition: all 0.3s ease;
        animation: pageLoad 0.8s ease;
      }

      @keyframes pageLoad {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .container {
        width: 100%;
        max-width: 1200px;
        background: var(--primary-bg);
        border-radius: 30px;
        padding: 40px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        margin-top: 20px;
        transition: all 0.3s ease;
        animation: containerFloat 1s ease 0.2s both;
      }

      @keyframes containerFloat {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      /* 拟态风格卡片 */
      .neumorphic-card {
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .neumorphic-inset {
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        transition: all 0.3s ease;
      }

      /* 玻璃态效果 */
      .glass-effect {
        background: var(--glass-bg);
        backdrop-filter: blur(10px);
        border: 1px solid var(--glass-border);
        border-radius: 20px;
      }

      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerSlide 0.8s ease 0.4s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateY(-30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 3.2rem;
        margin-bottom: 15px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        animation: titleGlow 3s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.2);
        }
      }

      .subtitle {
        font-size: 1.3rem;
        color: var(--text-secondary);
        margin-bottom: 30px;
        font-weight: 500;
      }

      .panels {
        display: flex;
        gap: 30px;
        margin-bottom: 40px;
        flex-wrap: wrap;
        animation: panelsSlide 0.8s ease 0.6s both;
      }

      @keyframes panelsSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .panel {
        flex: 1;
        min-width: 300px;
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
      }

      .panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .panel:hover::before {
        left: 100%;
      }

      .panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .panel-title {
        font-size: 1.6rem;
        margin-bottom: 25px;
        color: var(--accent-color);
        display: flex;
        align-items: center;
        font-weight: 600;
      }

      .panel-title::before {
        content: attr(data-icon);
        margin-right: 12px;
        font-size: 1.8rem;
        animation: iconBounce 2s ease-in-out infinite;
      }

      @keyframes iconBounce {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
      }

      .file-upload {
        position: relative;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        border: 2px solid transparent;
        border-radius: 25px;
        padding: 40px;
        text-align: center;
        transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        margin-bottom: 25px;
        background: var(--primary-bg);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        height: 260px;
        overflow: hidden;
        position: relative;
      }

      .file-upload::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 25px;
        padding: 2px;
        background: linear-gradient(
          135deg,
          var(--accent-color),
          var(--success-color),
          var(--accent-color)
        );
        mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
        mask-composite: exclude;
        opacity: 0;
        transition: opacity 0.3s ease;
      }

      .file-upload::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        width: 0;
        height: 0;
        background: radial-gradient(
          circle,
          rgba(102, 126, 234, 0.1) 0%,
          transparent 70%
        );
        border-radius: 50%;
        transform: translate(-50%, -50%);
        transition: all 0.4s ease;
        pointer-events: none;
      }

      .file-upload:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light),
          0 15px 40px rgba(102, 126, 234, 0.15);
      }

      .file-upload:hover::before {
        opacity: 1;
      }

      .file-upload:hover::after {
        width: 200px;
        height: 200px;
      }

      .file-upload.dragover {
        transform: translateY(-5px) scale(1.02);
        box-shadow: inset 8px 8px 16px rgba(78, 205, 196, 0.2),
          inset -8px -8px 16px rgba(255, 255, 255, 0.8),
          0 20px 50px rgba(78, 205, 196, 0.3);
      }

      .file-upload.dragover::before {
        opacity: 1;
        background: linear-gradient(
          135deg,
          var(--success-color),
          var(--accent-color),
          var(--success-color)
        );
      }

      .file-upload.dragover::after {
        width: 250px;
        height: 250px;
        background: radial-gradient(
          circle,
          rgba(78, 205, 196, 0.15) 0%,
          transparent 70%
        );
      }

      .file-upload input[type='file'] {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
        z-index: 10;
      }

      .file-upload-content {
        position: relative;
        z-index: 5;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 12px;
      }

      .file-upload-icon {
        font-size: 3rem;
        margin-bottom: 8px;
        transition: all 0.3s ease;
        filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1));
      }

      .file-upload:hover .file-upload-icon {
        transform: scale(1.1) rotate(5deg);
        filter: drop-shadow(3px 3px 6px rgba(0, 0, 0, 0.15));
      }

      .file-upload.dragover .file-upload-icon {
        transform: scale(1.2) rotate(-5deg);
        filter: drop-shadow(4px 4px 8px rgba(0, 0, 0, 0.2));
      }

      .file-upload-text {
        margin: 0;
        font-size: 1.1rem;
        font-weight: 600;
        color: var(--text-primary);
        text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8);
        transition: all 0.3s ease;
      }

      .file-upload-subtext {
        margin: 0;
        font-size: 0.95rem;
        font-weight: 400;
        color: var(--text-secondary);
        text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.6);
        transition: all 0.3s ease;
      }

      .file-upload:hover .file-upload-text {
        color: var(--accent-color);
        transform: translateY(-2px);
      }

      .file-upload:hover .file-upload-subtext {
        color: var(--text-primary);
        transform: translateY(-1px);
      }

      .file-upload.dragover .file-upload-text {
        color: var(--success-color);
        transform: translateY(-3px) scale(1.05);
      }

      .file-upload.dragover .file-upload-subtext {
        color: var(--success-color);
        transform: translateY(-2px) scale(1.02);
      }

      .file-upload-formats {
        margin-top: 8px;
        font-size: 0.8rem;
        color: var(--text-secondary);
        opacity: 0.7;
        transition: all 0.3s ease;
      }

      .file-upload:hover .file-upload-formats {
        opacity: 1;
        color: var(--accent-color);
      }

      .video-container {
        width: 100%;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-top: 20px;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .video-container:hover {
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light);
      }

      video {
        width: 100%;
        max-height: 400px;
        display: block;
        border-radius: 15px;
      }

      .controls {
        display: flex;
        justify-content: center;
        gap: 15px;
        margin-top: 20px;
        flex-wrap: wrap;
      }

      button {
        background: var(--primary-bg);
        color: var(--text-primary);
        border: none;
        padding: 14px 28px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        font-size: 1rem;
        flex-shrink: 0;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      button:hover::before {
        left: 100%;
      }

      button:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      button:active {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        padding: 16px 32px;
        font-size: 1.1rem;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-primary:hover {
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2),
          0 0 30px rgba(102, 126, 234, 0.3);
      }

      .result-container {
        display: flex;
        flex-wrap: wrap;
        gap: 20px;
        margin-top: 20px;
        min-height: 200px;
        background: var(--primary-bg);
        border-radius: 20px;
        padding: 20px;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light);
      }

      .screenshot-item {
        flex: 1;
        min-width: 250px;
        background: var(--primary-bg);
        border-radius: 15px;
        padding: 15px;
        text-align: center;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
        animation: screenshotSlideIn 0.5s ease;
      }

      @keyframes screenshotSlideIn {
        from {
          opacity: 0;
          transform: translateY(20px) scale(0.9);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .screenshot-item:hover {
        transform: translateY(-5px);
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
      }

      .screenshot-item img {
        width: 100%;
        border-radius: 10px;
        margin-bottom: 10px;
        max-height: 200px;
        object-fit: contain;
        box-shadow: inset 2px 2px 4px var(--shadow-dark),
          inset -2px -2px 4px var(--shadow-light);
      }

      .screenshot-info {
        display: flex;
        justify-content: space-between;
        font-size: 0.9rem;
        color: var(--text-secondary);
        margin-bottom: 10px;
        font-weight: 500;
      }

      .download-btn {
        background: var(--success-color);
        color: white;
        padding: 8px 16px;
        font-size: 0.9rem;
        border-radius: 10px;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .progress-container {
        margin: 25px 0;
        background: var(--primary-bg);
        border-radius: 15px;
        padding: 20px;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      .progress-bar {
        height: 12px;
        background: var(--primary-bg);
        border-radius: 6px;
        overflow: hidden;
        margin-bottom: 10px;
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
        position: relative;
      }

      .progress-fill {
        height: 100%;
        background: var(--accent-gradient);
        width: 0%;
        transition: width 0.3s ease;
        border-radius: 6px;
        position: relative;
        overflow: hidden;
      }

      .progress-fill::after {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.4),
          transparent
        );
        animation: progressShine 2s infinite;
      }

      @keyframes progressShine {
        0% {
          left: -100%;
        }
        100% {
          left: 100%;
        }
      }

      .progress-text {
        text-align: center;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .status-area {
        min-height: 50px;
        margin: 15px 0;
        padding: 15px;
        border-radius: 15px;
        background: var(--primary-bg);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      .status-message {
        color: var(--accent-color);
        font-weight: 600;
        animation: statusPulse 2s ease-in-out infinite;
      }

      @keyframes statusPulse {
        0%,
        100% {
          opacity: 1;
        }
        50% {
          opacity: 0.7;
        }
      }

      .error-message {
        color: var(--danger-color);
        font-weight: 600;
        animation: errorShake 0.5s ease-in-out;
      }

      @keyframes errorShake {
        0%,
        100% {
          transform: translateX(0);
        }
        25% {
          transform: translateX(-5px);
        }
        75% {
          transform: translateX(5px);
        }
      }

      .instructions {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        animation: instructionsSlide 0.8s ease 0.8s both;
      }

      @keyframes instructionsSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions h3 {
        color: var(--accent-color);
        margin-bottom: 15px;
        font-size: 1.4rem;
        font-weight: 600;
      }

      .instructions ol {
        padding-left: 20px;
        margin-bottom: 15px;
      }

      .instructions li {
        margin-bottom: 10px;
        line-height: 1.6;
        color: var(--text-secondary);
      }

      .instructions p {
        color: var(--text-secondary);
        line-height: 1.6;
        margin-bottom: 10px;
      }

      .instructions code {
        background: rgba(102, 126, 234, 0.1);
        padding: 2px 6px;
        border-radius: 4px;
        font-family: 'Courier New', monospace;
        color: var(--accent-color);
      }

      footer {
        margin-top: 30px;
        text-align: center;
        color: var(--text-secondary);
        font-size: 0.9rem;
        padding: 20px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        animation: footerSlide 0.8s ease 1s both;
      }

      @keyframes footerSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      /* 响应式设计优化 */
      @media (max-width: 1024px) {
        .panels {
          flex-direction: column;
          gap: 20px;
        }

        .panel {
          min-width: auto;
        }
      }

      @media (max-width: 768px) {
        body {
          padding: 10px;
        }

        .container {
          padding: 15px;
          margin-top: 10px;
          border-radius: 20px;
        }

        header {
          padding: 20px 15px;
          margin-bottom: 20px;
          border-radius: 20px;
        }

        h1 {
          font-size: 2.2rem;
          margin-bottom: 10px;
        }

        .subtitle {
          font-size: 1.1rem;
          margin-bottom: 20px;
        }

        .panels {
          gap: 15px;
          margin-bottom: 20px;
        }

        .panel {
          padding: 20px 15px;
          border-radius: 20px;
        }

        .panel-title {
          font-size: 1.3rem;
          margin-bottom: 20px;
        }

        .file-upload {
          padding: 25px 15px;
          height: 130px;
          margin-bottom: 20px;
          border-radius: 20px;
        }

        .file-upload-icon {
          font-size: 2.5rem;
          margin-bottom: 6px;
        }

        .file-upload-text {
          font-size: 1rem;
        }

        .file-upload-subtext {
          font-size: 0.9rem;
        }

        .file-upload-formats {
          font-size: 0.75rem;
          margin-top: 6px;
        }

        .controls {
          flex-direction: column;
          align-items: stretch;
          gap: 10px;
        }

        button {
          padding: 12px 20px;
          font-size: 0.95rem;
          width: 100%;
        }

        .btn-primary {
          padding: 14px 24px;
          font-size: 1rem;
        }

        .result-container {
          padding: 15px;
          min-height: 150px;
        }

        .screenshot-item {
          min-width: 100%;
          margin-bottom: 15px;
        }

        .instructions {
          padding: 20px 15px;
          margin-top: 20px;
          border-radius: 20px;
        }

        .instructions h3 {
          font-size: 1.2rem;
        }

        footer {
          padding: 15px;
          margin-top: 20px;
          border-radius: 15px;
          font-size: 0.85rem;
        }
      }

      @media (max-width: 480px) {
        body {
          padding: 8px;
        }

        .container {
          padding: 12px;
          border-radius: 15px;
        }

        header {
          padding: 15px 12px;
          border-radius: 15px;
        }

        h1 {
          font-size: 1.8rem;
        }

        .subtitle {
          font-size: 1rem;
        }

        .panel {
          padding: 15px 12px;
          border-radius: 15px;
        }

        .panel-title {
          font-size: 1.2rem;
          margin-bottom: 15px;
        }

        .file-upload {
          padding: 20px 12px;
          height: 210px;
          border-radius: 15px;
        }

        .file-upload-content {
          gap: 8px;
        }

        .file-upload-icon {
          font-size: 2rem;
          margin-bottom: 4px;
        }

        .file-upload-text {
          font-size: 0.9rem;
        }

        .file-upload-subtext {
          font-size: 0.8rem;
        }

        .file-upload-formats {
          font-size: 0.7rem;
          margin-top: 4px;
        }

        button {
          padding: 10px 16px;
          font-size: 0.9rem;
        }

        .btn-primary {
          padding: 12px 20px;
          font-size: 0.95rem;
        }

        .instructions {
          padding: 15px 12px;
        }

        .instructions ol {
          padding-left: 16px;
        }

        .instructions li {
          font-size: 0.9rem;
          margin-bottom: 8px;
        }

        footer {
          padding: 12px;
          font-size: 0.8rem;
        }
      }

      /* 暗色模式支持 */
      @media (prefers-color-scheme: dark) {
        :root {
          --primary-bg: #2d3748;
          --shadow-light: #4a5568;
          --shadow-dark: #1a202c;
          --text-primary: #f7fafc;
          --text-secondary: #a0aec0;
        }
      }

      /* 动画优化 */
      @media (prefers-reduced-motion: reduce) {
        *,
        *::before,
        *::after {
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
          transition-duration: 0.01ms !important;
        }
      }

      /* 自定义滚动条 */
      ::-webkit-scrollbar {
        width: 12px;
      }

      ::-webkit-scrollbar-track {
        background: var(--primary-bg);
        border-radius: 10px;
      }

      ::-webkit-scrollbar-thumb {
        background: var(--accent-color);
        border-radius: 10px;
        border: 2px solid var(--primary-bg);
      }

      ::-webkit-scrollbar-thumb:hover {
        background: var(--accent-gradient);
      }
    </style>
  </head>
  <body>
    <header>
      <h1>🎬 视频截图工具</h1>
      <p class="subtitle">基于 FFmpeg.wasm 技术 - 在浏览器中精准截取视频帧</p>
    </header>

    <div class="container">
      <div class="panels">
        <div class="panel">
          <h2 class="panel-title" data-icon="📁">1. 上传视频文件</h2>
          <div class="file-upload" id="fileDropArea">
            <div class="file-upload-content">
              <div class="file-upload-icon">🎬</div>
              <p class="file-upload-text">拖放视频文件到此处</p>
              <p class="file-upload-subtext">或点击选择文件</p>
              <p class="file-upload-formats">支持 MP4、MOV、AVI、MKV 等格式</p>
            </div>
            <input type="file" id="videoInput" accept="video/*" />
          </div>

          <div id="videoContainer" class="video-container">
            <video id="videoPlayer" controls>您的浏览器不支持视频播放</video>
          </div>

          <div class="controls">
            <button id="captureBtn" class="btn-primary" disabled>
              📸 截取当前帧
            </button>
            <button id="resetBtn">🔄 重置所有</button>
          </div>

          <div class="progress-container">
            <div class="progress-bar">
              <div class="progress-fill" id="progressFill"></div>
            </div>
            <div class="progress-text" id="progressText">🚀 准备就绪</div>
          </div>

          <div class="status-area">
            <div class="status-message" id="statusMessage"></div>
            <div class="error-message" id="errorMessage"></div>
          </div>
        </div>

        <div class="panel">
          <h2 class="panel-title" data-icon="🖼️">2. 截图结果</h2>
          <div id="resultContainer" class="result-container">
            <p
              style="
                text-align: center;
                width: 100%;
                padding: 40px 0;
                color: var(--text-secondary);
                font-size: 1.1rem;
              "
            >
              📷 截图将显示在这里
            </p>
          </div>

          <div class="controls">
            <button id="downloadAllBtn" disabled>📥 下载所有截图</button>
          </div>
        </div>
      </div>

      <div class="instructions">
        <h3>📖 使用说明：</h3>
        <ol>
          <li>🎥 上传视频文件（支持MP4、MOV、AVI等格式）</li>
          <li>🎮 使用视频播放器控制播放进度，找到想要截取的画面</li>
          <li>📸 点击"截取当前帧"按钮生成高清截图</li>
          <li>📥 截图会显示在右侧区域，可下载单张或所有截图</li>
          <li>🔄 使用"重置所有"按钮可以清除当前视频和截图</li>
        </ol>
        <p>
          💡 技术说明：使用FFmpeg的<code>-ss</code>参数指定时间点，<code
            >-vframes 1</code
          >参数截取单帧
        </p>
        <p>
          🔒
          注意：本工具完全在浏览器中运行，不会上传您的视频文件，确保隐私安全。
        </p>
      </div>
    </div>

    <footer>
      <p>
        ⚡ 基于 FFmpeg.wasm 技术实现 | 🌐 完全在浏览器中运行 | 🔐
        无需上传到服务器
      </p>
      <p>© 2025 网页版视频截图工具</p>
    </footer>

    <script>
      // FFmpeg实例
      let ffmpeg = null
      let inputFile = null
      let videoUrl = null
      let screenshots = []
      let screenshotCount = 0

      // DOM元素
      const videoInput = document.getElementById('videoInput')
      const videoPlayer = document.getElementById('videoPlayer')
      const captureBtn = document.getElementById('captureBtn')
      const resetBtn = document.getElementById('resetBtn')
      const downloadAllBtn = document.getElementById('downloadAllBtn')
      const statusMessage = document.getElementById('statusMessage')
      const errorMessage = document.getElementById('errorMessage')
      const progressFill = document.getElementById('progressFill')
      const progressText = document.getElementById('progressText')
      const resultContainer = document.getElementById('resultContainer')
      const fileDropArea = document.getElementById('fileDropArea')

      // 页面加载动画
      window.addEventListener('DOMContentLoaded', () => {
        document.body.style.opacity = '0'
        setTimeout(() => {
          document.body.style.transition = 'opacity 0.5s ease'
          document.body.style.opacity = '1'
        }, 100)
      })

      // 初始化事件监听
      function initEvents() {
        // 文件上传处理
        videoInput.addEventListener('change', handleFileUpload)

        // 截图按钮
        captureBtn.addEventListener('click', captureFrame)

        // 重置按钮
        resetBtn.addEventListener('click', resetAll)

        // 下载所有截图按钮
        downloadAllBtn.addEventListener('click', downloadAllScreenshots)

        // 拖放功能
        fileDropArea.addEventListener('dragover', (e) => {
          e.preventDefault()
          fileDropArea.classList.add('dragover')
        })

        fileDropArea.addEventListener('dragleave', () => {
          fileDropArea.classList.remove('dragover')
        })

        fileDropArea.addEventListener('drop', (e) => {
          e.preventDefault()
          fileDropArea.classList.remove('dragover')

          if (e.dataTransfer.files.length) {
            videoInput.files = e.dataTransfer.files
            handleFileUpload({ target: { files: e.dataTransfer.files } })
          }
        })
      }

      // 处理文件上传
      function handleFileUpload(event) {
        const file = event.target.files[0]
        if (!file) return

        // 检查文件类型
        if (!file.type.match('video.*')) {
          showError('❌ 请上传视频文件', errorMessage)
          return
        }

        inputFile = file
        videoUrl = URL.createObjectURL(file)

        // 设置视频源
        videoPlayer.src = videoUrl

        // 启用截图按钮
        captureBtn.disabled = false
        downloadAllBtn.disabled = true

        // 重置截图
        screenshots = []
        screenshotCount = 0
        updateResultContainer()

        statusMessage.textContent = `✅ 已加载视频: ${
          file.name
        } (${formatFileSize(file.size)})`
        errorMessage.textContent = ''
      }

      // 截取当前帧
      async function captureFrame() {
        if (!inputFile || !videoPlayer.src) {
          showError('❌ 请先上传视频文件', errorMessage)
          return
        }

        let currentTime = videoPlayer.currentTime
        if (currentTime <= 0) {
          currentTime = 0
        }

        // 显示进度
        progressFill.style.width = '0%'
        progressText.textContent = '🔄 初始化中...'
        captureBtn.disabled = true

        try {
          // 初始化FFmpeg
          if (!ffmpeg) {
            statusMessage.textContent = '🚀 正在加载FFmpeg引擎...'

            const { createFFmpeg, fetchFile } = FFmpeg
            ffmpeg = createFFmpeg({
              log: true,
              progress: ({ ratio }) => {
                const percent = Math.floor(ratio * 100)
                progressFill.style.width = `${percent}%`
                progressText.textContent = `⚡ 处理中: ${percent}%`
              },
            })

            await ffmpeg.load()
          }

          statusMessage.textContent = `📸 正在截取 ${formatTime(
            currentTime
          )} 的画面...`

          // 写入视频文件到虚拟文件系统
          const inputName = 'input.' + inputFile.name.split('.').pop()
          ffmpeg.FS('writeFile', inputName, await FFmpeg.fetchFile(inputFile))

          // 构建输出文件名
          const timestamp = Math.floor(currentTime)
          screenshotCount++
          const outputName = `screenshot_${screenshotCount}_${timestamp}s.jpg`

          // 执行FFmpeg截图命令
          await ffmpeg.run(
            '-ss',
            String(currentTime),
            '-i',
            inputName,
            '-vframes',
            '1',
            '-q:v',
            '2',
            outputName
          )

          // 读取输出文件
          const data = ffmpeg.FS('readFile', outputName)
          const blob = new Blob([data.buffer], { type: 'image/jpeg' })
          const url = URL.createObjectURL(blob)

          // 保存截图信息
          screenshots.push({
            id: screenshotCount,
            time: currentTime,
            url: url,
            blob: blob,
            filename: outputName,
          })

          // 更新结果展示
          updateResultContainer()

          progressText.textContent = '✅ 截图完成!'
          statusMessage.textContent = `🎉 成功截取 ${formatTime(
            currentTime
          )} 的画面`
          downloadAllBtn.disabled = false
        } catch (error) {
          console.error('截图失败:', error)
          showError(`❌ 截图失败: ${error.message}`, errorMessage)
        } finally {
          captureBtn.disabled = false
        }
      }

      // 更新结果展示区域
      function updateResultContainer() {
        if (screenshots.length === 0) {
          resultContainer.innerHTML =
            '<p style="text-align: center; width: 100%; padding: 40px 0; color: var(--text-secondary); font-size: 1.1rem;">📷 截图将显示在这里</p>'
          return
        }

        resultContainer.innerHTML = ''
        screenshots.forEach((screenshot, index) => {
          const item = document.createElement('div')
          item.className = 'screenshot-item'
          item.style.animationDelay = `${index * 0.1}s`
          item.innerHTML = `
                    <img src="${screenshot.url}" alt="视频截图">
                    <div class="screenshot-info">
                        <span>#${screenshot.id}</span>
                        <span>${formatTime(screenshot.time)}</span>
                    </div>
                    <button class="download-btn" data-id="${
                      screenshot.id
                    }">📥 下载</button>
                `
          resultContainer.appendChild(item)
        })

        // 添加下载按钮事件
        document.querySelectorAll('.download-btn').forEach((btn) => {
          btn.addEventListener('click', (e) => {
            const id = parseInt(e.target.getAttribute('data-id'))
            const screenshot = screenshots.find((s) => s.id === id)
            if (screenshot) {
              downloadScreenshot(screenshot)
            }
          })
        })
      }

      // 下载单张截图
      function downloadScreenshot(screenshot) {
        const a = document.createElement('a')
        a.href = screenshot.url
        a.download = screenshot.filename
        a.click()

        statusMessage.textContent = '📥 截图下载中...'
      }

      // 下载所有截图
      function downloadAllScreenshots() {
        screenshots.forEach((screenshot, index) => {
          setTimeout(() => {
            const a = document.createElement('a')
            a.href = screenshot.url
            a.download = screenshot.filename
            document.body.appendChild(a)
            a.click()
            document.body.removeChild(a)
          }, index * 200) // 延迟下载避免浏览器阻止
        })

        statusMessage.textContent = '📥 正在下载所有截图...'
      }

      // 重置所有
      function resetAll() {
        if (confirm('🤔 确定要重置所有内容吗？')) {
          screenshots = []
          screenshotCount = 0

          if (videoUrl) {
            URL.revokeObjectURL(videoUrl)
            videoUrl = null
          }

          // 释放截图URL
          screenshots.forEach((screenshot) => {
            URL.revokeObjectURL(screenshot.url)
          })

          videoInput.value = ''
          videoPlayer.src = ''
          captureBtn.disabled = true
          downloadAllBtn.disabled = true
          progressFill.style.width = '0%'
          progressText.textContent = '🚀 准备就绪'
          statusMessage.textContent = ''
          errorMessage.textContent = ''
          updateResultContainer()
        }
      }

      // 显示错误信息
      function showError(message, element) {
        element.textContent = message
        element.classList.add('error-shake')
        setTimeout(() => {
          element.classList.remove('error-shake')
          element.textContent = ''
        }, 5000)
      }

      // 格式化文件大小
      function formatFileSize(bytes) {
        if (bytes < 1024) return bytes + ' bytes'
        else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'
        else return (bytes / 1048576).toFixed(1) + ' MB'
      }

      // 格式化时间
      function formatTime(seconds) {
        const mins = Math.floor(seconds / 60)
        const secs = Math.floor(seconds % 60)
        return `${mins.toString().padStart(2, '0')}:${secs
          .toString()
          .padStart(2, '0')}`
      }

      // 初始化
      window.onload = initEvents
    </script>
  </body>
</html>
